#include <iostream>
#include <shlwapi.h>
#include "../libuploader/libxluploader.h"
#include "../3rd/include/freeimage/FreeImage.h"
using namespace std;

#pragma comment (lib, "shlwapi")

int progress_callback (
                       void *clientp,
                       double dltotal,
                       double dlnow,
                       double ultotal,
                       double ulnow
                      ) {
	cout << "dl: " << dlnow << "/" << dltotal << "; ul: " << ulnow << "/" << ultotal << endl;
	return 0;
}

int utHttp(int argc, char **argv);
int utProxy(int argc, char **argv);
void utImage(int argc, char **argv);
void utUpload2Imgur(int argc, char **argv);

// #define UT_HTTP
// #define UT_IMAGE
// #define UT_IMGUR_COM
#define UT_PROXY

// #define TEST_PCRE
int main(int argc, char **argv) {

#ifdef UT_HTTP
	return utHttp(argc, argv);
#elif defined (UT_IMAGE)
	utImage(argc, argv);
#elif defined (UT_IMGUR_COM)
	utUpload2Imgur(argc, argv);
#elif defined (UT_PROXY)
	return utProxy(argc, argv);
#endif
	return 0;
}



int utHttp(int argc, char **argv) {
#ifndef TEST_PCRE
	if (argc < 2) {
		std::cout << "usage: tester <file>[ <url>]" << std::endl;
		return 0;
	}
	char *file = argv[1];
	char *url = "http://tinypic.com";
	if (argc > 2) {
		url = argv[2];
	}

#if 1
	const TCHAR *t_file = NULL;
#ifdef UNICODE
	std::wstring ws = util_mbs2ws(file);
	t_file = ws.c_str();
#else
	t_file = file;
#endif
	// 	util_get_form_action_url_test();
	// 	return 0;

	// 	CSiteManager *pSiteManager = CSiteManager::getInstance();
	// 	cout << "we have " << pSiteManager->getSiteCount() << " sites" << endl;
	// 	return 0;

	// __asm int 3;
	ISite *pSite = debugGetSite();
	cout << "upload to " << util_w2utf8(pSite->getSiteName()) << endl;
	std::string image_url;
	HttpCode code = pSite->uploadFile(image_url, t_file, progress_callback);
	if (code == CURLE_OK) {
		cout << "get url: " << image_url << endl;
	} else if (code == ISite::PATTERN_NOT_FOUND) {
		cout << "can't find url from: " << endl << image_url << endl;
	} else {
		cout << "encounter an error: " << code << endl;
	}
	return 0;

	std::string response;
	std::string cookie;
	CURLcode res = http_upload(response, url, t_file, cookie, progress_callback);
	// cout << response << endl;
	if (res == CURLE_OK) {
		const char *str = response.c_str();
		// file_put_contents(_T("res.html"), response);
		cout << "we get: " << endl << response << endl;
	} else {
		cout << "upload failed with: " << res << endl;
	}
#else
	std::string contents;
	if (file_get_contentsA(file, contents)) {
		// cout << contents << endl;
		file_put_contentsA("1.png", contents);
	} else {
		cout << "read " << file << " failed" << endl;
	}
#endif
#else
	CURL *pCurl = curl_easy_init();
	curl_easy_cleanup(pCurl);
	pCurl = NULL;

	std::string html;
	if (!file_get_contents(_T("res.html"), html)) {
		cout << "read file failed" << endl;
		return -1;
	}

	// const char *pattern = "http:\\/\\/tinypic\\.com\\/view\\.php\\?pic=[^\"]*";
	const char *pattern = "http://tinypic\\.com/view\\.php\\?pic=([^\"]*)";
	const char *err = NULL;
	int err_offset = 0;
	int flags = PCRE_BSR_ANYCRLF | PCRE_UTF8 | PCRE_MULTILINE | PCRE_DOTALL;
	pcre *pcre_code = pcre_compile(pattern, flags, &err, &err_offset, NULL);
	if (!pcre_code) {
		cout << "compile pcre failed" << endl;
		return -1;
	}

	const char *text = html.c_str();
	int ovector[9] = {0};
	__asm int 3;
	int res = pcre_exec(pcre_code, NULL, text, html.length(), 0, 0, ovector, 9);
	if (res == 2) {
		std::string result = html.substr(ovector[0], ovector[1] - ovector[0]);
		cout << "found: " << result << endl;
		result = html.substr(ovector[2], ovector[3] - ovector[2]);
		cout << "found: " << result << endl;
	}
#endif
	return 0;
}


// #define USE_FREEIMAGE
#ifdef USE_FREEIMAGE
#ifdef UNICODE
#define FreeImage_GetFileTypeT      FreeImage_GetFileTypeU
#define FreeImage_LoadT             FreeImage_LoadU
#else
#define FreeImage_GetFileTypeT      FreeImage_GetFileType
#define FreeImage_LoadT             FreeImage_Load
#endif
#ifdef NDEBUG
#pragma comment (lib, "../3rd/libs/release/FreeImage.lib")
#else
#pragma comment (lib, "../3rd/libs/debug/FreeImage.lib")
#endif
#else
#include <gdiplus.h>
#pragma comment (lib, "gdiplus")
#endif
void utImage(int argc, char **argv) {

	TCHAR *files[] = {
		_T("D:\\dl\\temp\\mm\\0.jpg"),
		_T("D:\\dl\\temp\\mm\\1.jpg"),
		_T("D:\\dl\\temp\\mm\\2.jpg"),
		_T("D:\\dl\\temp\\mm\\3.jpg"),
		_T("D:\\dl\\temp\\mm\\4.jpg"),
		_T("D:\\dl\\temp\\mm\\5.jpg"),
		_T("D:\\dl\\temp\\mm\\6.jpg"),
		_T("D:\\dl\\temp\\mm\\7.jpg"),
		_T("D:\\dl\\temp\\mm\\8.jpg"),
		_T("D:\\dl\\temp\\mm\\9.jpg"),
	};

	int count = 0;
	DWORD dwTick = GetTickCount();
#ifdef USE_FREEIMAGE
	FreeImage_Initialise(FALSE);
	for (int i = 0; i < COUNT_OF(files); ++ i) {
		FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeT(files[i], 0);
		if (fif == FIF_UNKNOWN) {
			// TODO: report the error
			continue;
		}

		FIBITMAP *bitmap = FreeImage_LoadT(fif, files[i], 0);
		if (bitmap == NULL) {
			// TODO: report the error
			continue;
		}

		int w = FreeImage_GetWidth(bitmap);
		int h = FreeImage_GetHeight(bitmap);
#if 0
		if (w > 120 || h > 160) {
			int size = 160;
			if ((float)w / (float)120 > (float)h / (float)160) {
				size = 120;
			}

			FIBITMAP *thumbnail = FreeImage_MakeThumbnail(bitmap, size);
			std::swap(thumbnail, bitmap);
			FreeImage_Unload(thumbnail);
		}

		w = FreeImage_GetWidth(bitmap);
		h = FreeImage_GetHeight(bitmap);


		HDC hdc = ::GetDC(NULL);
		// below copied from http://freeimage.sourceforge.net/faq.html
		HBITMAP hBitmap = ::CreateDIBitmap(
			hdc, 
			FreeImage_GetInfoHeader(bitmap), 
			CBM_INIT,
			FreeImage_GetBits(bitmap),
			FreeImage_GetInfo(bitmap),
			DIB_RGB_COLORS);
		::ReleaseDC(NULL, hdc);
		::DeleteObject(hBitmap);
#endif

		FreeImage_Unload(bitmap);
		bitmap = NULL;

		count ++;
	}

	FreeImage_DeInitialise();
#else
	using namespace Gdiplus;
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	for (int i = 0; i < COUNT_OF(files); ++ i) {
		Image *img = Image::FromFile(files[i]);
		int x = img->GetWidth();
		int y = img->GetHeight();
#if 0
		Image *thumbnail = img.GetThumbnailImage(1440, 900, NULL, NULL);
		if (thumbnail) {
			HDC hdc = ::GetDC(NULL);
			Graphics *g = new Graphics(hdc);
			// g->DrawImage(thumbnail, 0, 0, thumbnail->GetWidth(), thumbnail->GetHeight());
			delete g;
			ReleaseDC(NULL, hdc);
			delete thumbnail;
		}
#endif
		delete img;
		count ++;
	}

	GdiplusShutdown(gdiplusToken);
#endif
	dwTick = GetTickCount() - dwTick;

	cout << "Load and create thumbnail for " << count << " files used " << dwTick << " ms" << endl;
}


void utUpload2Imgur(int argc, char **argv) {
	if (argc != 2) {
		std::cout << "usage: tester <img pathname>" << std::endl;
		return;
	}

	tstring fileName = util_mbs2tcs(argv[1]);
	if (!PathFileExists(fileName.c_str())) {
		std::cout << argv[1] << " not exists!" << std::endl;
		return;
	}
	std::string url = "http://imgur.com/";
	std::string response;
	std::string cookie;
	HttpCode res = http_upload(response, url, fileName.c_str(), cookie, progress_callback, NULL);
	if (res == CURLE_OK) {
		// std::cout << response;
		const char *pattern_pic = "http://imgur.com/[a-zA-Z0-9]+\\.[a-zA-Z]+";
		int flags = PCRE_BSR_ANYCRLF | PCRE_UTF8 | PCRE_MULTILINE | PCRE_DOTALL;
		const char *err = NULL;
		int errOffset = 0;
		pcre *codePic = pcre_compile(pattern_pic, flags, &err, &errOffset, NULL);
		const int size = 30;
		int ov[size] = {0};
		const char *text = response.c_str();
		int res = pcre_exec(codePic, NULL, text, response.length(), 0, 0, ov, size);
		if (res != 1) {
			std::cout << "parse error" << std::endl;
		} else {
			std::string url = response.substr(ov[0], ov[1] - ov[0]);
			std::cout << "url: " << url << std::endl;
		}
		pcre_free(codePic);
	}
}

int utProxy(int argc, char **argv) {
	if (argc != 2) {
		std::cout << "usage: tester <url>" << std::endl;
		return -1;
	}
	std::string proxy = "127.0.0.1:8000";
	std::cout << "use " << proxy << " as proxy" << std::endl;
	http_set_proxy(proxy);

	std::string html, cookie;
	http_get(html, argv[1], cookie);
	std::cout << "get html:" << std::endl << html << std::endl << std::endl << "cookie: " << cookie << std::endl;
	return 0;
}